<?php
declare (strict_types=1);

namespace app\admin\controller\admin;

use app\admin\annotation\common\Auth;
use app\admin\controller\Admin;
use app\admin\model\admin\Role as RoleModel;
use app\admin\validate\admin\Role as RoleValidate;
use app\admin\service\common\SortableService;
use app\common\Constants;
use Raiseinfo\Tools;
use think\App;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Lang;
use think\facade\Log;
use think\Request;

class Role extends BaseRole
{
    public function __construct(
        App $app,
        protected RoleModel  $roleModel,
        protected Tools $tools,
    )
    {
        parent::__construct($app, $roleModel);
    }

    #[Auth('admin:role:permission')]
    public function getPermission(): \think\response\Json
    {
        try {
            $role_id = $this->request->post('role_id');
            $menu_codes = Db::name('admin_role')->alias('a')
                ->leftJoin('admin_role_menu b', 'a.id = b.role_id')
                ->leftJoin('dev_menu c', 'b.menu_id = c.id')
                ->where('a.id', $role_id)
                ->whereNull('c.delete_time')
                ->column('c.code');
            $action_codes = Db::name('admin_role')->alias('a')
                ->leftJoin('admin_role_action b', 'a.id = b.role_id')
                ->leftJoin('dev_action c', 'c.id = b.action_id')
                ->where('a.id', $role_id)
                ->whereNull('c.delete_time')
                ->column('c.code');
            $merged_codes = array_merge($menu_codes, $action_codes);
            $filtered_codes = array_filter($merged_codes);
            $result = array_values($filtered_codes);
            return $this->success(['data' => $result]);
        } catch (\Exception $e) {
            throw $e;
        }
    }


    #[Auth('admin:role:permission')]
    public function setPermission(): \think\response\Json
    {
        try {
            $fields = "role_id,ids";
            $data = $this->request->only(explode(',', $fields), 'post');

            if (empty($data['role_id']) || !isset($data['ids'])) {
                return $this->error(['message' => '缺少必要的参数：role_id 或 ids']);
            }

            Db::startTrans();

            $role = RoleModel::with(['menus', 'actions'])->find($data['role_id']);
            if (!$role) {
                Db::rollback();
                return $this->error(['message' => '指定的角色不存在']);
            }

            $menu_ids = [];
            $action_ids = [];

            foreach ($data['ids'] as $value) {
                if ($value < 10000) {
                    $menu_ids[] = $value;
                } else {
                    $action_ids[] = $value - 10000;
                }
            }

            $role->menus()->detach();
            if (!empty($menu_ids)) {
                $role->menus()->attach($menu_ids);
            }


            $role->actions()->detach();
            if (!empty($action_ids)) {
                $role->actions()->attach($action_ids);
            }

            Db::commit();

            return $this->success();
        } catch (\Exception $e) {
            Db::rollback();
            trace($e->getMessage(), 'debug');
            return $this->error(['message' => Constants::E_COMMON_SORT_DATA_FAILED]);
        }
    }

    #[Auth('admin:role:permission')]
    public function getMenuTreeOptions(): \think\response\Json
    {
        try {
            $list = [];
            $lang = Lang::getLangSet();
            $menuList = Db::name('dev_menu')->alias('a')
                ->leftJoin('admin_i18n b', "a.key = b.key and b.lang_code = '{$lang}'")
                ->field('a.id,a.pid,a.code,a.name,a.route_path,b.value')
                ->where('a.status', 1)
                ->whereNull('a.delete_time')
                ->select()
                ->toArray();
            foreach ($menuList as $menu) {
                $list[] = [
                    'id' => (int)$menu['id'],
                    'pid' => (int)$menu['pid'],
                    'type' => 'menu',
                    // 'code' => $menu['code'] ?: $menu['name'],
                    'code' => $menu['code'],
                    'label' => $menu['value'] ? $menu['value'] . '【' . $menu['route_path'] . '】' : $menu['name'],
                ];
            }
            $actionList = Db::name('dev_action')->alias('a')
                ->leftJoin('admin_i18n b', "a.key = b.key and b.lang_code = '{$lang}'")
                ->field('a.id,a.menu_id,a.code,a.title,a.url,a.method,b.value')
                ->where('a.status', 1)
                ->whereNull('a.delete_time')
                ->select()
                ->toArray();
            foreach ($actionList as $action) {
                $list[] = [
                    'id' => 10000 + $action['id'], // ID加前缀防止冲突
                    'pid' => (int)$action['menu_id'], // 操作的父ID就是它所属的菜单ID
                    'type' => 'action',
                    'code' => $action['code'],
                    'label' => $action['value'] ? $action['value'] . '【' . $action['method'] . '】' : $action['title'],
                ];
            }
            $tree = $this->tools->buildTree($list, true, 0, 'id', 'pid');
            return $this->success(['data' => $tree]);
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }


}
